let logger = require("pomelo-logger").getLogger(__filename);
let configCreator = require("../entities/config").create;
let configLoader = require("../entities/config").loadFromDocument;

let ConfigService = function (app) {
    this.app = app;
    this.configs = [];
};

ConfigService.prototype.initialize = function () {
    let configDao = this.app.get("configDao");
    //load from mongo
    configDao.findAllConfigs(documents => {
        documents.forEach(document => {
            let config = configLoader(document);
            this.configs.push(config);
        });
    });
};

ConfigService.prototype.getConfigs = function () {
    return this.configs;
};

ConfigService.prototype.getSerializeConfigs = function () {
    let serializeConfigs = [];
    for(let config of this.configs) {
        serializeConfigs.push(config.toJSON());
    }
    return serializeConfigs;
};

ConfigService.prototype.getConfigByKey = function (key) {
    for(let config of this.configs) {
        if(config.key === key) {
            return config;
        }
    }
    return null;
};

ConfigService.prototype.getEnableConfigValueByKey = function (key) {
    for(let config of this.configs) {
        if(config.key === key && config.enable === true) {
            return config.value;
        }
    }
    return null;
};

ConfigService.prototype.findConfigByKey = function (key, callback) {
    let configDao = this.app.get("configDao");
    configDao.findByKey(key, document => {
        if(!document) {
            callback(null);
            return;
        }
        callback(configLoader(document));
    });
};

ConfigService.prototype.updateConfigValue = function (key, value, callback) {
    let configDao = this.app.get("configDao");
    if(!this.contains(key)) {
        callback(null);
        return;
    }
    for(let config of this.configs) {
        if(key === config.key) {
            configDao.updateValue(key, value, result => {
                if(!result || result.result.ok != 1) {
                    logger.info(`config updateConfig error. document null`);
                    callback(null);
                    return;
                }
                config.value = value;
                callback(key);
            });
        }
    }
};

ConfigService.prototype.updateConfigEnable = function (key, enable, callback) {
    let configDao = this.app.get("configDao");
    if(!this.contains(key)) {
        callback(null);
        return;
    }
    for(let config of this.configs) {
        if(key === config.key) {
            configDao.updateEnable(key, enable, result => {
                if(!result || result.result.ok != 1) {
                    logger.info(`config updateConfig error. document null`);
                    callback(null);
                    return;
                }
                config.enable = enable;
                callback(key);
            });
        }
    }
};

ConfigService.prototype.upsertConfigValue = function (key, value, callback) {
    let configDao = this.app.get("configDao");
    // let config = configCreator(key, value);
    configDao.upsertValue(key, value, result => {
        if(!result || result.result.ok != 1) {
            logger.info(`updateConfig error. result null`);
            callback(null);
            return;
        }
        this.upsertValue(key, value);
        callback(key);
    });
};

ConfigService.prototype.addConfig = function (key, value, desc, enable, callback) {
    let configDao = this.app.get("configDao");
    if(this.contains(key)) {
        callback(null);
        return;
    }
    let config = configCreator(key, value, desc, enable);
    configDao.insertOne(config.toBSON(), result => {
        if(!result || result.result.ok != 1) {
            logger.info(`addConfig error. result empty`);
            callback(null);
            return;
        }
        this.configs.push(config);
        callback(config);
    });
};

ConfigService.prototype.deleteConfigByKey = function (key, callback) {
    let configDao = this.app.get("configDao");
    configDao.deleteByKey(key, result => {
        if(!result || result.ok != 1) {
            logger.info(`deleteConfigKey error. id empty`);
            callback(null);
            return;
        }
        this.delete(key);
        callback(key);
    });
};

ConfigService.prototype.contains = function(key){
    for(let config of this.configs) {
        if(config.key === key) {
            return true;
        }
    }
    return false;
};

ConfigService.prototype.upsertValue = function (key, value) {
    for(let config of this.configs) {
        if(config.key === key) {
            config.value = value;
            return;
        }
    }
    this.configs.push(configCreator(key, value));
};

ConfigService.prototype.delete = function (key) {
    let newConfigs = [];
    for(let config of this.configs) {
        if(config.key !== key) {
            newConfigs.push(config);
        }
    }
    this.configs = newConfigs;
};

ConfigService.prototype.toJSON = function () {
    let serializeConfigs = [];
    for(let config of this.configs) {
        serializeConfigs.push(config.toJSON());
    }
    return serializeConfigs;
};

ConfigService.prototype.toEffectiveJSON = function () {
    let serializeConfigs = [];
    for(let config of this.configs) {
        if(config.enable === true || config.enable === "true") {
            serializeConfigs.push(config.toSimpleJSON());
        }
    }
    return serializeConfigs;
};

module.exports.create = function (app) {
    return new ConfigService(app);
};
